const http = require('http')
const moment = require('moment')
const _ = require('lodash')
const date = require('./date')

const sinaServer = 'http://int.dpool.sina.com.cn/iplookup/iplookup.php'
  + '?format=json&ip=';

module.exports = {
  ipLookUp: (ip, cb) => {
    let url = sinaServer + ip
    http.get(url, (res) => {
      let code = res.statusCode
      if (code === 200) {
        res.on('data', (data) => {
          try {
            cb(null, JSON.parse(data))
          }
          catch (err) {
            cb(err)
          }
        })
        return;
      }
      cb({ code: code })
    })
  },
  // 净化输入参数 seller_id
  parseQuerySellerId: (sellerId) => {
    let id = parseInt(sellerId);
    if (isNaN(id) || id <= 0) {
      return false;
    }
    return id;
  },
  assembleOutput: function(data, flag) {
    let output = {
      pv: {
        _obj: {},
      },
      iv: {
        _obj: {},
      },
    }
    this.fillIn(output, data, flag)
    let ipArr = []
    // 订单量
    let orderQuantity = 0
    data.forEach((value) => {
      if (ipArr.indexOf(value.ip)) {
        ipArr.push(value.ip)
      }
      if (value.order !== undefined) {
        let orderId = value.order.id
        if (orderId !== 'null') {
          orderQuantity++
        }
      }
    })
    output.pv.quantity = data.length
    output.iv.quantity = _.uniq(ipArr).length
    // 订单转化率 order convert rate
    let percentage = (output.pv.quantity === 0) ? '0%' : (orderQuantity / output.pv.quantity * 100).toFixed(2) + '%';
    output.ocr = percentage
    // 获取额外统计信息
    this.fetchAdditionalInfo(output, data, flag)

    return output
  },
  fillIn: function(output, data, flag) {
    let pvPointArr = []
    let ivPointArr = []

    data.forEach((value) => {
      let createdAt = value.created_at
      let ip = value.ip
      let d = new Date(createdAt)
      let hour = d.getHours()

      let arr = this.getItemArr(value, flag)

      pvPointArr.push(arr[0])
      ivPointArr.push(arr[1])
    })

    let pvObj = this.statistic(pvPointArr)
    let ivObj = this.statistic(ivPointArr)
    ivObj = this.rebuild(ivObj)

    let pvFormat = date.outputFormat(flag)
    let ivFormat = date.outputFormat(flag)

    Object.keys(pvObj).forEach((val) => {
      pvFormat[val] = pvObj[val]
    })
    Object.keys(ivObj).forEach((val) => {
      ivFormat[val] = ivObj[val]
    })

    output.pv._obj = pvFormat;
    output.pv.keys = this.xAxisDisplayFormat(flag, Object.keys(pvFormat))
    output.pv.values = this.objectValues(pvFormat)
    output.iv._obj = ivFormat
    output.iv.values = this.objectValues(ivFormat)
  },
  getItemArr: (value, flag) => {
    let createdAt = value.created_at
    let ip = value.ip
    let d = new Date(createdAt)
    let hour = moment(createdAt).format('HH') + ':00'

    let rsArr = []

    switch (flag) {
      case 'today':
      case 'yesterday':
        // 当天的统计数据
        // 昨天的统计数据
        rsArr = [hour, hour + '@' + ip];
        break
      case 'week':
        // 一周的统计数据
        let prefix = moment(createdAt).format('dddd');
        if (hour >= 12) {
          rsArr = [prefix + '$PM', prefix + '$PM' + '@' + ip];
          break
        }
        rsArr = [prefix + '$AM', prefix + '$AM' + '@' + ip];
        break
      case 'month':
        // 一月的统计数据
        let monthDate = createdAt.substr(5, 5);
        rsArr = [monthDate, monthDate + '@' + ip];
        break
      case 'halfyear':
        // 近六个月的统计数据
        let date = d.getDate()
        let yearMonth = createdAt.substr(0, 7)
        if (date >= 15) {
          rsArr = [yearMonth + '#' + '1', yearMonth + '#' + '1' + '@' + ip];
          break
        }
        rsArr = [yearMonth + '#' + '0', yearMonth + '#' + '0' + '@' + ip];
        break
    }
    return rsArr
  },
  statistic: (arr) => {
    let rs = {}
    for (let i = 0; i < arr.length; ++i) {
      if (!rs[arr[i]]) {
        rs[arr[i]] = 0
      }
      ++rs[arr[i]]
    }
    return rs
  },
  xAxisDisplayFormat: function(flag, keyArr) {
    if (flag === 'week') {
      keyArr = keyArr.map((currentValue) => {
        return currentValue.replace(/\$/, '@')
      })
    } else if (flag === 'halfyear') {
      keyArr = keyArr.map((currentValue) => {
        if (currentValue.indexOf('#0') !== -1) {
          return currentValue.replace(/#0/, '上半月')
        }
        else if (currentValue.indexOf('#1') !== -1) {
          return currentValue.replace(/#1/, '下半月')
        }
        else {
          return currentValue
        }
      });
    }

    return keyArr
  },
  objectValues: function(obj) {
    let keys = Object.keys(obj)
    let values = []
    keys.forEach((val) => {
      values.push(obj[val])
    })
    return values
  },
  fetchAdditionalInfo: function(output, data, flag) {
    let browserArr = []
    let districtArr = []
    data.forEach((value) => {
      if (value.browser !== undefined) {
        browserArr.push(value.browser.name)
      }
      districtArr.push(value.district)
    })
    let len = browserArr.length
    let browserObj = this.statistic(browserArr)
    let districtObj = this.statistic(districtArr)

    Object.keys(browserObj).forEach((val) => {
      browserObj[val] = (browserObj[val] / len * 100).toFixed(2) + '%'
    })
    output.browser = browserObj
    output.browserArr = this.objToArr(browserObj)
    output.browserObjArr = this.convert2ObjArr(browserObj)

    Object.keys(districtObj).forEach((val) => {
      districtObj[val] = (districtObj[val] / districtArr.length * 100).toFixed(2) + '%';
    })
    output.district = districtObj
    output.districtArr = this.objToArr(districtObj)
    output.districtObjArr = this.convert2ObjArr(districtObj)
  },
  objToArr: function(obj) {
    let keys = Object.keys(obj)
    let arr = []
    keys.forEach((key) => {
      arr.push([key, parseInt(obj[key])])
    })
    return arr
  },
  convert2ObjArr: function(obj) {
    let keys = Object.keys(obj)
    let arr = []
    keys.forEach((key) => {
      let subObj = {
        value: parseInt(obj[key]),
        name: key,
      }
      arr.push(subObj)
    })
    return arr
  },
  rebuild: function(obj) {
    let keyArr = Object.keys(obj);
    let newKeyArr = [];
    keyArr.forEach((val) => {
      newKeyArr.push(val);
    });

    newKeyArr = newKeyArr.map((currentValue) => {
      return currentValue.split('@')[0];
    });

    return this.statistic(newKeyArr);
  },
  judgeStartAt: function(str) {
    let startAt = ''
    switch (str) {
      case 'week':
        // bug? first day of a week is Sunday
        // startAt = moment().day('Monday').format('YYYY-MM-DD');
        startAt = this.getMonday().toLocaleString().substr(0, 10)
        break
      case 'month':
        startAt = moment().date(1).format('YYYY-MM-DD')
        break
      case 'halfyear':
        startAt = moment().add(-6, 'month').format('YYYY-MM-DD')
        break
      default:
        startAt = ''
    }
    return startAt
  },
  getMonday: () => {
    const d = new Date()
    let day = d.getDay()
    // adjust when day is Sunday
    let diff = d.getDate() - day + (day == 0 ? - 6 : 1)
    return new Date(d.setDate(diff))
  },
}
